home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / reve / makemove.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  10KB  |  384 lines

  1. /*LINTLIBRARY*/
  2.  
  3. /*  @(#)makemove.c 1.15 91/11/13
  4.  *
  5.  *  Interface to best computer strategy routines used by Reve.
  6.  *
  7.  *  Copyright (C) 1990, 1991 - Rich Burridge & Yves Gallot.
  8.  *  All rights reserved.
  9.  *
  10.  *  Permission is granted to copy this source, for redistribution
  11.  *  in source form only, provided the news headers in "substantially
  12.  *  unaltered format" are retained, the introductory messages are not
  13.  *  removed, and no monies are exchanged.
  14.  *
  15.  *  Permission is also granted to copy this source, without the
  16.  *  news headers, for the purposes of making an executable copy by
  17.  *  means of compilation, provided that such copy will not be used
  18.  *  for the purposes of competition in any othello tournaments, without
  19.  *  prior permission from the authors.
  20.  *
  21.  *  No responsibility is taken for any errors on inaccuracies inherent
  22.  *  either to the comments or the code of this program, but if reported
  23.  *  (see README file), then an attempt will be made to fix them.
  24.  */
  25.  
  26. #include "reve.h"
  27. #include "color.h"
  28. #include <unistd.h>
  29. #include <signal.h>
  30. #include "extern.h"
  31.  
  32.  
  33. void
  34. display_time(player, timeleft)    /* Display time left in mm:ss format. */
  35. int player, timeleft ;
  36. {
  37.   enum panel_type ptype ;
  38.   int mins, secs ;
  39.  
  40.   mins = timeleft / 60 ;
  41.   secs = timeleft % 60 ;
  42.   ptype = (player == BLACK) ? BLACK_CLOCK : WHITE_CLOCK ;
  43.   SPRINTF(items[(int) ptype].text, "%1d:%02d", mins, secs) ;
  44.   if (DO_CLOCK) draw_clock(W_PANEL, ptype, DO_CLOCK) ;
  45. }
  46.  
  47.  
  48. void
  49. domove(pos, mv, nextpos, player)
  50. BOARD *pos, *nextpos ;
  51. int mv, player ;
  52. {
  53.   register int i ;
  54.   if (pos != nextpos) FOR_BOARD(i) nextpos->square[i] = pos->square[i] ;
  55.  
  56.   s_move = mv ;
  57.   s_row = mv >> 3 ;
  58.   s_col = mv & 7 ;
  59.   s_player = player ;
  60.   s_opponent = -player ;
  61.   s_flip = TRUE ;
  62.   s_pos = nextpos ;
  63.  
  64.   nextpos->square[s_move] = player ;
  65.  
  66.   (void) sandwich(-9) ;
  67.   (void) sandwich(-8) ;
  68.   (void) sandwich(-7) ;
  69.   (void) sandwich(-1) ;
  70.   (void) sandwich(1) ;
  71.   (void) sandwich(7) ;
  72.   (void) sandwich(8) ;
  73.   (void) sandwich(9) ;
  74.  
  75.   nextpos->moves_left = (pos->moves_left) - 1 ;
  76. }
  77.  
  78.  
  79. FILE *
  80. find_file(filename)
  81. char *filename ;
  82. {
  83.   char name[MAXLINE], *paths, *ptr ;
  84.   int i = 0 ;
  85.   FILE *fp = NULL ;
  86.  
  87.   if ((fp = fopen(filename, "r")) == NULL)
  88.     {
  89.       paths = getenv("PATH") ;
  90.       if ((ptr = paths) && filename[0] != '/')
  91.         for (;;)
  92.           if (*ptr == ':' || *ptr == 0)
  93.             {
  94.               if (*ptr == 0) break ;
  95.               name[i++] = '/' ;
  96.               name[i] = 0 ;
  97.               STRCAT(name, edgefile) ;
  98.               if ((fp = fopen(name, "r")) != NULL) break ;
  99.               if (*ptr == '\0') break ;
  100.               ptr++ ;
  101.               i = 0 ;
  102.             }
  103.           else name[i++] = *ptr++ ;
  104.     }
  105.   return(fp) ;
  106. }
  107.  
  108.  
  109. int
  110. fork_child()
  111. {
  112.   char *argv[6] ;         /* Reve_proc command line arguments. */
  113.   int i, tabsiz ;
  114.  
  115.   PIPE(pipe_io[0]) ;      /* Setup input pipe. */
  116.   PIPE(pipe_io[1]) ;      /* Setup output pipe. */
  117.   switch (pid = fork())
  118.     {
  119.       case -1 : CLOSE(pipe_io[0][0]) ;
  120.                 CLOSE(pipe_io[0][1]) ;
  121.                 CLOSE(pipe_io[1][0]) ;
  122.                 CLOSE(pipe_io[1][1]) ;
  123.                 perror("reve fork failed") ;
  124.                 exit(1) ;
  125.       case  0 : DUP2(pipe_io[0][0], 0) ;         /* Child. */
  126.                 DUP2(pipe_io[1][1], 1) ;
  127.                 DUP2(pipe_io[1][1], 2) ;
  128.  
  129. #ifdef NOGETDTAB
  130. #ifdef hpux
  131.                 tabsiz = _NFILE ;
  132. #else
  133.                 tabsiz = sysconf(_SC_OPEN_MAX) ;
  134. #endif /*hpux*/
  135. #else
  136.                 tabsiz = getdtablesize() ;
  137. #endif /*NOGETDTAB*/
  138.  
  139.                 for (i = tabsiz; i > 2; i--) CLOSE(i) ;
  140.                 for (i = 0; i < NSIG; i++) SIGNAL(i, SIG_DFL) ;
  141.                 i = 0 ;
  142.                 argv[i++] = "reve_proc" ;
  143.                 argv[i++] = "-e" ;
  144.                 argv[i++] = edgefile ;
  145.                 if (saveres == TRUE) argv[i++] = "-log" ;
  146.                 if (debug   == TRUE) argv[i++] = "-debug" ;
  147.                 argv[i] = (char *) NULL ;
  148.                 execvp(reveproc, argv) ;
  149.                 perror("reve child exec") ;
  150.                 _exit(-1) ;
  151.       default : CLOSE(pipe_io[0][0]) ;           /* Parent. */
  152.                 CLOSE(pipe_io[1][1]) ;
  153.     }
  154.   return(pid) ;
  155. }
  156.  
  157.  
  158. void
  159. init_clocks()               /* Setup timer clocks. */
  160. {
  161.   items[(int) BLACK_CLOCK].value = timevals[level] * 60 ;
  162.   items[(int) WHITE_CLOCK].value = timevals[level] * 60 ;
  163.   SPRINTF(items[(int) BLACK_CLOCK].text, "%1d:00", timevals[level]) ;
  164.   SPRINTF(items[(int) WHITE_CLOCK].text, "%1d:00", timevals[level]) ;
  165. }
  166.  
  167.  
  168. int
  169. legal(mv, player, pos)
  170. BOARD *pos ;
  171. int mv, player ;
  172. {
  173.   if (pos->square[mv]) return(FALSE) ;     /* Already occupied */
  174.  
  175.   s_move = mv ;
  176.   s_row = mv >> 3 ;
  177.   s_col = mv & 7 ;
  178.   s_player = player ;
  179.   s_opponent = -player ;
  180.   s_flip = FALSE ;
  181.   s_pos = pos ;
  182.  
  183.   return(sandwich(-9) + sandwich(-8) + sandwich(-7) + sandwich(-1) +
  184.          sandwich(1)  + sandwich(7)  + sandwich(8)  + sandwich(9)) ;
  185. }
  186.  
  187.  
  188. void
  189. read_from_reve(fd)
  190. int fd ;
  191. {
  192.   struct reve_out out ;
  193.   int reply, sout ;
  194.  
  195.   if (!started) return ;
  196.   sout = sizeof(struct reve_out) ;
  197.   if ((reply = read(fd, (char *) &out, sout)) > 0)
  198.     {
  199.       profmax = out.depth ;
  200.            if (out.type == M_BEST) show_best(out.move, out.note) ;
  201.       else if (out.type == M_MOVE)
  202.         {
  203.           set_cursor(CANVASCUR) ;
  204.           move = out.move ;
  205.           note = out.note ;
  206.           opponent_move(next_player) ;
  207.         }
  208.       else if (out.type == M_SUGGESTION)
  209.         {
  210.           if (legal(out.move, next_player, &board) == 0)
  211.             FOR_BOARD(out.move)
  212.               if (board.square[out.move] == FREE &&
  213.                   legal(out.move, next_player, &board)) break ;
  214.           do_suggest(next_player, out.move, out.note, IS_ON) ;
  215.           if (restore_moves) show_all(IS_ON) ;
  216.           sstate     = IS_ON ;
  217.           suggestion = out.move ;
  218.           snote      = out.note ;
  219.           processing = FALSE ;
  220.         }
  221.     }
  222.   else
  223.     {
  224.       FPRINTF(stderr, "Couldn't get connection to reve_proc. Exiting.\n",
  225.               progname) ;
  226.       destroy_reve() ;
  227.     }
  228. }
  229.  
  230.  
  231. void
  232. reset_clock(player)
  233. int player ;
  234. {
  235.   time_t tval ;
  236.  
  237.   start_time = tval = time((time_t *) 0) ;   /* Get local time from kernel. */
  238.   if (player == BLACK) last_btime = tval ;
  239.   else                 last_wtime = tval ;
  240. }
  241.  
  242.  
  243. void
  244. reset_time(timeleft)
  245. time_t timeleft ;
  246. {
  247.   struct reve_in in ;
  248.  
  249.   in.type = M_TIME ;
  250.   in.timeleft = timeleft ;
  251.   WRITE(pipe_io[0][1], (char *) &in, sizeof(struct reve_in)) ;
  252. }
  253.  
  254.  
  255. /*  Test whether the square move sandwiches a line
  256.  *  of enemy pieces in the direction [row_inc, col_inc];
  257.  *  If (s_flip) then update position by capturing such pieces
  258.  *  Returns the number of pieces captured.
  259.  */
  260.  
  261. int
  262. sandwich(increment)
  263. register int increment ;
  264. {
  265.   register int square, offset ;
  266.   int row_offset, col_offset, piece, piece_count ;
  267.   int pcount = 0 ;
  268.  
  269.   if ((s_move+increment) < 0 || (s_move+increment) > 63) return(pcount) ;
  270.   if (s_pos->square[s_move+increment] != s_opponent)     return(pcount) ;
  271.  
  272. /*  Quick test to catch most failures -
  273.  *  note that the tested square may not even
  274.  *  be on the board, but the condition is a
  275.  *  sufficient one for failure.
  276.  */
  277.  
  278.   row_offset = (increment < -1 ? s_row  :      /* inc -1: -9, -8, -7 */
  279.     increment >  1 ? 7-s_row : 8) ;            /* inc  1:  7,  8,  9 */
  280.   col_offset = (increment & 4 ? s_col   :      /* inc -1: -9, -1,  7 */
  281.     increment & 1 ? 7-s_col : 8) ;             /* inc  1: -7,  1,  9 */
  282.  
  283.   offset = (row_offset > col_offset ? col_offset : row_offset) ;
  284.  
  285. /* offset = shortest distance to an edge in the direction of search */
  286.  
  287.   if (2 > offset) return(pcount) ;
  288.  
  289.   piece_count = 1 ;
  290.   square = s_move+increment ;
  291.  
  292.   while (--offset)
  293.     {
  294.       if (!(piece = s_pos->square[square += increment]))
  295.         return(pcount) ;        /* If empty square, give up */
  296.  
  297.       if (piece == s_player) break ;
  298.       else piece_count++ ;      /* Count opponent's pieces encountered */
  299.     }
  300.  
  301.   if (!offset) return(pcount) ;
  302.  
  303.   pcount = piece_count ;
  304.   if (s_flip)
  305.     while (piece_count--)
  306.       s_pos->square[square -= increment] = s_player ;
  307.  
  308.   return(pcount) ;
  309. }
  310.  
  311.  
  312. void
  313. update_clock(player, doinc)   /* Decrement the clock for the current user. */
  314. int player, doinc ;
  315. {
  316.   char str[MAXLINE] ;
  317.   int diff, n, timeleft ;
  318.   time_t cur_time, last_time ;
  319.  
  320.   diff = 0 ;
  321.   cur_time  = time((time_t *) 0) ;
  322.   last_time = (player == BLACK) ? last_btime : last_wtime ;
  323.   if (cur_time != last_time) diff = (int) (cur_time - last_time) ;
  324.   if (doinc && diff <= 0) diff = 1 ;
  325.   else if (diff <= 0) return ;
  326.   if (player == BLACK)
  327.     {
  328.       last_btime = cur_time ;
  329.       n = (int) BLACK_CLOCK ;
  330.     }
  331.   else
  332.     {
  333.       last_wtime = cur_time ;
  334.       n = (int) WHITE_CLOCK ;
  335.     }
  336.   items[n].value -= diff ;
  337.   if (items[n].value < 0) items[n].value = 0 ;
  338.   display_time(player, items[n].value) ;
  339.   if (DO_CLOCK && items[n].value == 0)
  340.     {
  341.       cmode = GAME_OVER ;
  342.       SPRINTF(str, "Timer expired for %s. ***GAME OVER***",
  343.               (player == BLACK) ? bstone_name : wstone_name) ;
  344.       message(PANEL_MES, str) ;
  345.       beep() ;
  346.     }
  347. }
  348.  
  349.  
  350. int
  351. valid_move(board, player)      /* Check if valid move for this player. */
  352. BOARD *board ;
  353. int player ;
  354. {
  355.   int mv ;
  356.   int valid ;      /* Set if there is a valid move. */
  357.  
  358.   for (mv = 0; mv < 64; mv++)
  359.     if (board->square[mv] == FREE)
  360.       {
  361.         valid = legal(mv, player, board) ;
  362.         if (valid > 0) return(TRUE) ;
  363.       }
  364.   return(FALSE) ;
  365. }
  366.  
  367.  
  368. /*ARGSUSED*/
  369. void
  370. write_to_reve(mtype, reve_board, player, level)
  371. enum move_type mtype ;
  372. int *reve_board, player, level ;
  373. {
  374.   int i ;
  375.   struct reve_in in ;
  376.  
  377.   for (i = 0; i < 64; i++) in.board[i] = reve_board[i] ;
  378.   in.player   = player ;
  379.   in.level    = level ;
  380.   in.type     = mtype ;
  381.   processing  = TRUE ; 
  382.   WRITE(pipe_io[0][1], (char *) &in, sizeof(struct reve_in)) ; 
  383. }
  384.